package com.base.themvx.widget

import android.content.Context
import android.util.AttributeSet
import android.view.View
import androidx.annotation.Px
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.base.themvx.AppLog
import com.base.themvx.adapter.AbsSelectableAdapter
import com.base.themvx.adapter.MenuAdapter
import com.base.themvx.defNonSyncLazy
import com.base.themvx.model.MenuItemData

/**
 * 菜单项(列表)的 RecyclerView 封装
 * @date 2022-02-18
 */
class MenuDatasRecyclerView(context: Context, attributeSet: AttributeSet?) :
    RecyclerView(context, attributeSet), AbsSelectableAdapter.OnItemMultyClickListener {
    constructor(context: Context) : this(context, null)

    private val mTag by defNonSyncLazy {
        "MenuDatasRecyclerView"
    }

    /**
     * 菜单项的适配器
     */
    private var mAdapterOfMenuDatas: MenuAdapter? = null

    private var mMenuList: MutableList<MenuItemData> = mutableListOf()

    /**
     * 两个菜单选项之间的间隔 宽度
     * 单位：像素
     */
    @Px
    var mMenuItemsGapBetween: Int = 0

//    /**
//     * 外部没有指定[mMenuItemsGapBetween]时，是否需要自动分配Item间间距
//     */
//    var mIsNeedAutoSetItemGap = false

    /**
     * 中间菜单项的占据宽度
     * 如果在没有 中间 占位 item的情况下，应该置为 0
     * 单位：像素
     */
    @Px
    var mMiddleMenuHoldWidth: Int = 0

    /**
     * 是否允许 本菜单项可滚动
     * def = false
     */
    var mIsAllowScroll: Boolean = false

    /**
     * 当外部传入的 菜单项为 偶数时，是否需要自动添加一个中间 item以让两侧 对称
     */
    var mIsNeedAutoAddMiddleHoldItem = false

    init {
        val datasAdapter = MenuAdapter()
        datasAdapter.mOnItemMultyClickListener = this
        mAdapterOfMenuDatas = datasAdapter
        adapter = datasAdapter
        //默认为 水平方向列表
        layoutManager =
            object : LinearLayoutManager(context, HORIZONTAL, false) {
                override fun canScrollHorizontally(): Boolean {
                    return mIsAllowScroll
                }
            }
    }

    /**
     * 添加一个菜单项
     */
    fun addMenuItem(aMenuItem: MenuItemData): MenuDatasRecyclerView {
        mMenuList.add(aMenuItem)
        return this
    }

    fun addMenuItems(menuItems: Collection<MenuItemData>): MenuDatasRecyclerView {
        if (menuItems.isNotEmpty()) {
            mMenuList.addAll(menuItems)
        }
        return this
    }

    /**
     * 添加 菜单项
     */
    fun addMenuItems(vararg menuItems: MenuItemData): MenuDatasRecyclerView {
        if (menuItems.isNotEmpty()) {
            for (menuItem in menuItems) {
                mMenuList.add(menuItem)
            }
            //java.lang.NoClassDefFoundError: kotlin.collections.ArraysKt
            //	at kotlin.collections.ArraysKt.asList(ArraysKt.java:0)
            //	at kotlin.collections.CollectionsKt__MutableCollectionsKt.addAll(CollectionsKt__MutableCollectionsKt.java:141)
            //	at kotlin.collections.CollectionsKt.addAll(CollectionsKt.java:0)
//            mMenuList.addAll(menuItems)
        }
        return this
    }

    /**
     * 设置 新的 菜单项数据集,之后需要 重新调用 [showMenuDatas]
     * @see [showMenuDatas]
     */
    fun setNewMenuItems(menuItems: Collection<MenuItemData>): MenuDatasRecyclerView {
        if (menuItems.isNotEmpty()) {
            mMenuList = menuItems.toMutableList()
        }
        return this
    }

    /**
     * 调用该方法，开始显示 菜单项
     */
    fun showMenuDatas() {
        val takeWidth = measuredWidth
        AppLog.i(mTag, "--> showMenuDatas() takeWidth = $takeWidth")
        if (takeWidth < 1) {
            post(mDelayAdjTask)
        } else {
            adjPerItemLayout()
        }
    }

    private val mDelayAdjTask: Runnable by defNonSyncLazy {
        Runnable {
            val takeWidth = measuredWidth
            if (takeWidth < 1) {
                postDelayed(mDelayAdjTask,100)
                return@Runnable
            }
            adjPerItemLayout()
        }
    }

    /**
     * 调整 各菜单项的布局
     */
    private fun adjPerItemLayout() {
        val menuList = mMenuList
        var menuCount = menuList.size
        if (menuCount > 0) {
            val menuItemGapBetween = mMenuItemsGapBetween
//            if (menuCount > 5) {//这里不做依Item数量来主动指定Item间间距了，外部有需要直接设置[mMenuItemsGapBetween]
//                if (menuItemGapBetween < 1) {
//                    menuItemGapBetween = CommonBgBuilder.mDp16Px
//                    mMenuItemsGapBetween = menuItemGapBetween
//                }
//            }
            if (mIsNeedAutoAddMiddleHoldItem && menuCount > 1 && menuCount % 2 == 0) {//2个以上并且是偶数
                val firstMiddleIndex = menuCount / 2
                val defHoldItem = MenuItemData()
                defHoldItem.isVisiable = false
                menuList.add(firstMiddleIndex, defHoldItem)
            }
            menuCount = menuList.size
            //是否有中间占位 item的指定 宽
            val middleItemHoldWidth = mMiddleMenuHoldWidth
            var leftCanUseWidth = measuredWidth - paddingStart - paddingEnd - middleItemHoldWidth
            AppLog.e(mTag, "--> adjPerItemLayout() leftCanUseWidth = $leftCanUseWidth")
            //中间的 菜单的 index
            val middleIndex = menuCount / 2
            var totalGapWidth = 0
            val isNeedAdjPerItems = middleItemHoldWidth > 0 || menuItemGapBetween > 0
            if (isNeedAdjPerItems) {
                menuList.forEachIndexed { index, menuItemData ->
                    when (index) {
                        middleIndex -> {//中间 菜单项
                            if (middleItemHoldWidth > 0) {
                                menuItemData.menuWidth = middleItemHoldWidth
                                menuItemData.menuMarginNext = 0
                            } else {
                                if (menuItemData.menuMarginNext == 0) {
                                    menuItemData.menuMarginNext = menuItemGapBetween
                                    totalGapWidth += menuItemGapBetween
                                }
                            }
                        }

                        middleIndex - 1 -> {//中间项的前一项
                            if (middleItemHoldWidth > 0) {
                                menuItemData.menuMarginNext = 0
                            } else {
                                if (menuItemData.menuMarginNext == 0) {
                                    menuItemData.menuMarginNext = menuItemGapBetween
                                    totalGapWidth += menuItemGapBetween
                                }
                            }
                        }

                        menuCount - 1 -> {//最后一菜单项
                            menuItemData.menuMarginNext = 0
                        }

                        else -> {
                            menuItemData.menuMarginNext = menuItemGapBetween
                            totalGapWidth += menuItemGapBetween
                        }
                    }
                }
            }
            leftCanUseWidth -= totalGapWidth
            val finalPerMenuWidth = if (middleItemHoldWidth > 0) {//有中间占位Item
                leftCanUseWidth / (menuCount - 1)
            } else {
                leftCanUseWidth / menuCount
            }
            mAdapterOfMenuDatas?.assignItemWidth = finalPerMenuWidth
        }
        mAdapterOfMenuDatas?.setList(menuList)
//        mAdapterOfMenuDatas?.setNewData(mMenuList)
//        mAdapterOfMenuDatas?.items = mMenuList
    }

    //    /**
//     * 菜单项 每个 item 的点击事件
//     */
//    override fun onItemClick(view: View?, position: Int) {
//        mMenuOptCallback?.onMenuOptCallback(mMenuList[position], position)?.let {allowOpt ->
//            if (allowOpt) {
//                mAdapterOfMenuDatas?.handleItemClicked(position,true)
//            }
//        }
//    }
    private var mMenuOptCallback: IMenuOptCallback? = null

    /**
     * 供外部 设置 菜单项的 点击/操作 的 监听者,具体点击了菜单项 要做什么事，由外部决定
     */
    fun setMenuItemOptListener(l: IMenuOptCallback?) {
        this.mMenuOptCallback = l
    }

    fun updateMenuHintMsgCount(theMenuType: String, newHintMsgCount: Int) {
        mMenuList.forEachIndexed { index, menuItemData ->
            if (theMenuType == menuItemData.menuType) {
                menuItemData.msgHintCount = newHintMsgCount
                mAdapterOfMenuDatas?.notifyItemChanged(
                    index,
                    MenuAdapter.PAYLOAD_MENU_HINT_COUNT_CHANGED
                )
                return
            }
        }
    }

    fun effectMenuHintMsgCount(theMenuType: String, effectedMsgCount: Int) {
        mMenuList.forEachIndexed { index, menuItemData ->
            if (theMenuType == menuItemData.menuType) {
                menuItemData.msgHintCount += effectedMsgCount
                mAdapterOfMenuDatas?.notifyItemChanged(
                    index,
                    MenuAdapter.PAYLOAD_MENU_HINT_COUNT_CHANGED
                )
                return
            }
        }
    }

    /**
     * 标记一个 菜单项被选中
     * @param theMenuType 目标菜单类型
     * @param isNeedCallbackSelectedIt true: 自动回调通知外部该菜单项选中了；
     */
    fun markMenuItemSelected(theMenuType: String?, isNeedCallbackSelectedIt: Boolean) {
        if (theMenuType.isNullOrBlank()) {
            return
        }
        mMenuList.find {
            theMenuType == it.menuType
        }?.let { item ->
            markMenuItemSelected(item, isNeedCallbackSelectedIt)
        }
    }

    /**
     * 标记一个菜单项被选中
     * @param theMenuItem 菜单项
     * @param isNeedCallbackSelectedIt true: 自动回调通知外部该菜单项选中了；
     */
    fun markMenuItemSelected(theMenuItem: MenuItemData?, isNeedCallbackSelectedIt: Boolean) {
        theMenuItem?.let {
            val isSelected = mAdapterOfMenuDatas?.markItemDataSelectedOrNot(true, it)
            if (isNeedCallbackSelectedIt && isSelected == true) {
                mMenuOptCallback?.onMenuOptCallback(it, -1)
            }
        }
    }

    interface IMenuOptCallback {
        /**
         * 关于菜单项 点击/操作 的 信息回调
         * @param theMenuData 被点击/操作 的菜单项数据
         * @param theMenuPosition 菜单项在菜单列表中的 位序；大多数情况下不需要
         * @param isDoubleCheck true: 当前为双击
         * @return true: 监听者/外部 允许了本次菜单操作； false: 监听者/外部 不允许/拦截 本次菜单的操作 (将不会切换)
         */
        fun onMenuOptCallback(
            theMenuData: MenuItemData,
            theMenuPosition: Int,
            isDoubleCheck: Boolean = false
        ): Boolean?
    }

    /**
     * itemView 的 双击 事件
     * @param adapter 当前的适配器
     * @param isDoubleClick true: 当前是双击；false: 非双击
     * @param view 双击的 View
     * @param position itemView的位置
     */
    override fun onItemMultyClick(
        adapter: AbsSelectableAdapter<*, *>,
        isDoubleClick: Boolean,
        view: View,
        position: Int
    ) {
        mMenuOptCallback?.onMenuOptCallback(mMenuList[position], position, isDoubleClick)
            ?.let { allowOpt ->
                if (allowOpt) {
                    mAdapterOfMenuDatas?.theItemClicked(position, true)
                }
            }
    }

    fun notifyDatasChanged(){
        mAdapterOfMenuDatas?.notifyDataSetChanged()
    }
}